import Taro, {getCurrentInstance} from "@tarojs/taro";
import {Toast} from "@antmjs/vantui";
import {v4 as uuidv4} from 'uuid';

import JsonUtils from "@/utils/json_utils";
import LocalData from "@/common/local_data";
import LocalUtils from "@/utils/local_utils";

interface ModalCallback {
  (confirmed: boolean): void;
}

type EventActionCallback = (data: any) => void; // 你可以将 any 替换为更具体的 data 类型
export default class Utils {
  static getRandomInt(min, max) {
    min = Math.ceil(min);
    max = Math.floor(max);
    return Math.floor(Math.random() * (max - min)) + min; // The maximum is exclusive and the minimum is inclusive
  }

  static delay(sec: number) {
    return new Promise(resolve => setTimeout(resolve, sec * 1000));
  }
  static copyToClipboard() {
    Taro.setClipboardData({
      data: LocalData.acceptAddress,
      success: () => {
        Utils.showOkToast('复制成功');
      }
    });
  }

  static formatISODateToLocal(isoDateString: string, options?: Intl.DateTimeFormatOptions) {
    const date = new Date(isoDateString);
    return date.toLocaleString();
  }

  static showToast(params) {
    Taro.showToast(params).then(r => {
    });
  }

  static showErrorToast(title: string) {
    Taro.showToast({
      title: title,
      icon: 'none',
    }).then(r => {
    });
  }

  static navigateAndListenToEvent(url: string,
                                  eventName: string, // 允许指定事件名称，使其更通用
                                  onEventAction: EventActionCallback): void {
    Taro.navigateTo({
      url: url,
      success: (res) => {
        if (res.eventChannel) {
          res.eventChannel.on(eventName, (data) => {
            onEventAction(data);
          });
          // 你也可以在这里添加 res.eventChannel.emit() 来向目标页面发送初始数据，如果需要的话
        } else {
        }
      },
      fail: (err) => {
        // 在这里可以添加错误处理逻辑，例如显示一个提示
        Taro.showToast({
          title: '页面跳转失败',
          icon: 'none',
          duration: 2000
        });
      }
    });
  }

  static showOkToast(title: string) {
    Taro.showToast({
      title: title,
    }).then(r => {
    });
  }

  static navigateTo(params) {
    Taro.navigateTo(params).then(r => {
    });
  }


  static showShareImageMenu(params) {
    Taro.showShareImageMenu(params).then(r => {
    });
  }

  static reLaunch(params) {
    Taro.reLaunch(params).then(r => {
    });
  }

  static setTitle(title) {
    Taro.setNavigationBarTitle({
      title: title
    }).then(r => {
    });
  }

//
  static navigateBack(params?) {
    params = params || {
      delta: 1
    };
    Taro.navigateBack(params).then(r => {
    });
  }

  static navigateToThen(params) {
    return Taro.navigateTo(params);
  }

  static redirectTo(params) {
    Taro.redirectTo(params).then(r => {
    });
  }

  static switchTab(params) {
    Taro.switchTab(params).then(r => {
    });
  }


  static isWeapp() {
    return Taro.getEnv() === Taro.ENV_TYPE.WEAPP;
  }

  static addAccessToken(params) {
    return {...params, accessToken: '1111'};
  }

  static isNotBlank(value) {
    if (typeof value === 'string') {
      return value.trim() !== '';
    }
    return !(value === null || value === undefined);
  }

  static isMobilePhone(phone: string): boolean {
    // 使用正则表达式验证手机号格式，适用于中国大陆手机号
    if (!phone) return false;
    const reg = /^1[3-9]\d{9}$/;
    return reg.test(phone);
  }

  static showLoading(title: string = '请稍候...', mask: boolean = true): void {
    Taro.showLoading({
      mask: mask,
      title: title
    }).then(r => {
    });
  }

  static clear(): void {
    Toast.clear()
  }

  static toast(text: string = "出错啦~", duration: number = 2000, success: boolean = false): void {
    Taro.showToast({
      title: text,
      icon: success ? 'success' : 'none',
      duration: duration
    }).then(r => {
    });
  }

  static modal(
    title: string = '提示',
    content: string,
    showCancel: boolean,
    callback?: ModalCallback,
    confirmColor: string = "#5677fc",
    confirmText: string = "确定"
  ): void {
    Taro.showModal({
      title: title,
      content: content,
      showCancel: showCancel,
      cancelColor: "#555",
      confirmColor: confirmColor,
      confirmText: confirmText,
      success(res) {
        if (res.confirm) {
          callback && callback(true);
        } else {
          callback && callback(false);
        }
      }
    }).then(r => {
    });
  }

  static isEmpty(collection: any[] | undefined) {
    return !collection || collection.length === 0;
  }

  static getDefaultArray(collection: any[] | undefined): any[] {
    return Utils.isEmpty(collection) ? [] : collection as any[];
  }


  static getUrlWithObject(url: string, params: any): string {
    if (!params) {
      return url;
    }
    const queryString = encodeURIComponent(JsonUtils.stringify(params))
    return `${url}?data=${queryString}`;
  }

  static getObjectWithUrl<T>(params: any): T {
    const dataString = decodeURIComponent(params);
    return JsonUtils.parse<T>(dataString);
  }

  //判断字符串不为空，并且大于0
  static isThanZero(value: string | number | null | undefined): boolean {
    if (value === null || typeof value === 'undefined') {
      return false;
    }

    let stringValue: string;
    if (typeof value === 'number') {
      // 如果是数字，可以直接比较，或者转换为字符串进行统一处理
      // return value > 0; // 如果是数字，这是最直接的
      stringValue = String(value); // 为了与字符串情况统一 parseFloat 逻辑
    } else { // value is string
      stringValue = value;
    }
    if (stringValue.trim() === '') {
      return false;
    }
    const numericValue = parseFloat(stringValue);
    return !Number.isNaN(numericValue) && numericValue > 0;
  }

  static generateUuidV4(): string | null {
    return uuidv4();
  }

  static getChannel(instance) {
    if (instance.page && instance.page.getOpenerEventChannel) {
      const openerEventChannel = instance.page.getOpenerEventChannel();
      if (openerEventChannel) {
        return openerEventChannel as Taro.EventChannel;
      } else {
      }
      return null
    }
  }

  static getI(): getCurrentInstance.Current {
    return Taro.getCurrentInstance();
  }


  static getParamsByRouter(instance: getCurrentInstance.Current) {
    if (instance && instance.router && instance.router.params) {
      return instance.router.params;
    }
    return null;
  }


  static emit(i: (Taro.EventChannel | null | undefined), key, value) {
    if (i) {
      i.emit(key, value)
    }
  }

  static stopRefresh() {
    Taro.stopPullDownRefresh()
  }

  static classNames(...args) {
    const classes = [];
    for (const arg of args) {
      if (typeof arg === 'string' && arg) {
        classes.push(arg);
      } else if (typeof arg === 'object' && arg !== null) {
        for (const key in arg) {
          if (Object.prototype.hasOwnProperty.call(arg, key) && arg[key]) {
            classes.push(key);
          }
        }
      }
    }
    return classes.join(' ');
  }


  /**
   * 将基础路径和参数对象拼接成一个完整的 URL。
   *
   * @param basePath 基础路径，例如 "/captcha" 或 "http://example.com/api/users"
   * @param params 一个包含查询参数的键值对对象。
   *               值为 null 或 undefined 的参数将被忽略。
   * @returns 拼接好的完整 URL 字符串。
   */
  static buildUrlWithParams(basePath: string, params?: QueryParams): string {
    if (!params || Object.keys(params).length === 0) {
      return basePath; // 如果没有参数，直接返回基础路径
    }

    const queryParams: string[] = [];

    for (const key in params) {
      // 使用 Object.prototype.hasOwnProperty.call 来确保只处理对象自身的属性，而不是原型链上的
      if (Object.prototype.hasOwnProperty.call(params, key)) {
        const value = params[key];

        // 忽略值为 null 或 undefined 的参数
        if (value !== null && typeof value !== 'undefined') {
          // 对键和值都进行 URL 编码，以处理特殊字符
          const encodedKey = encodeURIComponent(key);
          const encodedValue = encodeURIComponent(String(value)); // 将布尔值和数字转换为字符串
          queryParams.push(`${encodedKey}=${encodedValue}`);
        }
      }
    }

    if (queryParams.length === 0) {
      return basePath; // 如果所有参数都是 null/undefined，也直接返回基础路径
    }

    // 检查 basePath 是否已经包含查询参数
    const separator = basePath.includes('?') ? '&' : '?';

    return `${basePath}${separator}${queryParams.join('&')}`;
  }

  //判断是不是合法的手机号
  static isPhoneNumber(phoneNumber: string): boolean {
    // 正则表达式用于验证手机号格式
    const phoneRegex = /^1[3-9]\d{9}$/;
    // 使用正则表达式进行验证
    return phoneRegex.test(phoneNumber);
  }

  static scanFile(url) {
    const path = LocalUtils.getLocalStr(url)
    if (Utils.isNotBlank(path)) {
      Utils.openFile(path)
    } else {
      Utils.showLoading("正在下载")
      Utils.downloadFile(url)
    }
  }

  static openFile(filePath) {
    const fileType = Utils.getFileType(filePath)
    if (fileType === LocalData.UNKNOWN_FILE_TYPE_SWITCH) {
      Taro.previewImage({
        current: '',
        urls: [filePath],
        success: function (res2) {
          //toast

        }
      });
    } else {
      Taro.openDocument({
        filePath: filePath,
        showMenu: true,
        success: function (res2) {
          //toast

        }
      })
    }
  }


  static downloadFile(url) {
    Taro.downloadFile({
      url: url,//服务器上的pdf地址
      success: function (res) {
        Taro.hideLoading()
        LocalUtils.setLocalStr(url, res.tempFilePath)
        Utils.openFile(res.tempFilePath)
      }
    })
  }

  //
  static getFileType(filePath: string | null | undefined): string {
    if (!filePath || filePath.trim() === '') {
      return LocalData.UNKNOWN_FILE_TYPE_SWITCH;
    }
    const lastDotIndex = filePath.lastIndexOf('.');
    if (lastDotIndex === -1 || lastDotIndex === 0 || lastDotIndex === filePath.length - 1) {
      return LocalData.UNKNOWN_FILE_TYPE_SWITCH;
    }
    const extension = filePath.substring(lastDotIndex + 1).toLowerCase();
    switch (extension) {
      case 'doc':
      case 'docx':
      case 'xls':
      case 'xlsx':
      case 'ppt':
      case 'pptx':
      case 'pdf':
        return extension; // 直接返回匹配到的扩展名
      // case 'jpeg': // 如果想将 jpeg 归类为 jpg
      //   return 'jpg';
      default:
        return LocalData.UNKNOWN_FILE_TYPE_SWITCH;
    }
  }

  static openPDFDocument(url: string) {
    const link = document.createElement('a');
    link.href = url;
    link.target = '_blank';
    link.download = ''; // 可设置文件名，留空则使用原文件名
    link.click();
  };

  static buildUrlFromLaunchOptions(options?: Taro.getLaunchOptionsSync.LaunchOptions):string{
    if (!options || !options.path) {
      return '';
    }
    let url = options.path;
    const query = options.query;
    if (query && Object.keys(query).length > 0) {
      const filteredQuery = {};
      for (const [key, value] of Object.entries(query)) {
        // 过滤掉 stamp 参数
        if (key === 'stamp') {
          continue;
        }
        // 对参数值进行解码
        filteredQuery[key] = decodeURIComponent(String(value));
      }
      const queryString = Object.entries(filteredQuery)
        .map(([key, value]) => `${encodeURIComponent(key)}=${encodeURIComponent(String(value))}`)
        .join('&');
      url += `?${queryString}`;
    }
    return url;
  }
}

interface QueryParams {
  [key: string]: string | number | boolean | null | undefined;
}

